package com.miku.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.miku.mikuapicommon.model.entity.ProductInfo;
import com.miku.mikuapicommon.model.entity.ProductOrder;
import com.miku.mikuapicommon.model.entity.RechargeActivity;
import com.miku.project.common.ErrorCode;
import com.miku.project.exception.BusinessException;
import com.miku.project.model.enums.PaymentStatusEnum;
import com.miku.project.model.enums.ProductTypeStatusEnum;
import com.miku.project.model.vo.ProductOrderVo;
import com.miku.project.model.vo.UserVO;
import com.miku.project.service.OrderService;
import com.miku.project.service.ProductOrderService;
import com.miku.project.service.RechargeActivityService;
import com.miku.project.utils.RedissonLockUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.time.Instant;
import java.util.List;

import static com.miku.project.model.enums.PayTypeStatusEnum.ALIPAY;
import static com.miku.project.model.enums.PayTypeStatusEnum.WX;

/**
 * 订单服务
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Resource
    private RedissonLockUtil redissonLockUtil;
    @Resource
    private List<ProductOrderService> productOrderServices;
    @Resource
    private ProductOrderService productOrderService;
    @Resource
    private ProductInfoServiceImpl productInfoService;
    @Resource
    private RechargeActivityService rechargeActivityService;
    /**
     * 根据支付类型创建订单
     *
     * @param productId
     * @param payType
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProductOrderVo createOrderByPayType(Long productId, String payType, UserVO loginUser) {

        //按付费类型获取产品订单服务的Bean
        ProductOrderService orderService = getProductOrderServiceByPayType(payType);

        //获取分布式锁
        String redissonLock=("getOrder:"+loginUser.getUserAccount().intern());

        //加锁
        ProductOrderVo getProductOrderVo=redissonLockUtil.redissonDistributedLocks(redissonLock,()->{
            //订单存在就返回不再创建
            return productOrderService.getProductOrder(productId,loginUser,payType);
        });
        if (getProductOrderVo != null){
            return getProductOrderVo;
        }
        redissonLock=("createOrder:"+loginUser.getUserAccount().intern());
        return redissonLockUtil.redissonDistributedLocks(redissonLock,()->{
            //检查是否购买充值活动
            checkBuyRechargeActivity(loginUser.getId(),productId);
            //保存订单,返回vo信息
            return orderService.saveProductOrder(productId,loginUser);
        });

    }


    /**
     * 检查购买重置活动
     * @param userId
     * @param productId
     */
    private void checkBuyRechargeActivity(Long userId, Long productId) {
        ProductInfo productInfo=productInfoService.getById(productId);
        if (productInfo.getProductType().equals(ProductTypeStatusEnum.RECHARGE_ACTIVITY.getValue())){
            //购买充值活动
            long orderCount = productOrderService.count(Wrappers.<ProductOrder>lambdaQuery()
                    .eq(ProductOrder::getUserId, userId)
                    .eq(ProductOrder::getProductId, productId)
                    .eq(ProductOrder::getStatus, PaymentStatusEnum.NOTPAY.getValue())
                    .or().eq(ProductOrder::getStatus, PaymentStatusEnum.SUCCESS.getValue()));
            if (orderCount>0){
                //已经购买了充值活动
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"该商品只能购买一次，请查看是否已经创建了该订单，或者挑选其他商品吧！");
            }
            long count = rechargeActivityService.count(Wrappers.<RechargeActivity>lambdaQuery()
                    .eq(RechargeActivity::getUserId, userId)
                    .eq(RechargeActivity::getProductId, productId));
            if (count>0){
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "该商品只能购买一次，请查看是否已经创建了该订单，或者挑选其他商品吧！！");

            }
        }
    }

    /**
     * 按照付费类型获取产品订单服务
     * @param payType
     * @return
     */
    @Override
    public ProductOrderService getProductOrderServiceByPayType(String payType) {

        return productOrderServices.stream()
                .filter(s->{
                    //获取付费类型注解
                    Qualifier annotation = s.getClass().getAnnotation(Qualifier.class);
                    //判断付费类型是否支持
                    return annotation !=null  && annotation.value().equals(payType);
                })
                //获取第一个付费类型注解支持的bean
                .findFirst()
                //判断付费类型是否支持
                .orElseThrow(()->new BusinessException(ErrorCode.PARAMS_ERROR,"付费类型不支持"));
    }

    /**
     * 解析订单通知结果
     * @param notifyDate
     * @param request
     * @return
     */
    @Override
    public String doOrderNotify(String notifyDate, HttpServletRequest request) {
        String payType;
        if (notifyDate.startsWith("gmt_create=") && notifyDate.contains("gmt_create")&&notifyDate.contains("sign_type")&&notifyDate.contains("notify_type")){
//            payType=ALIPAY.getValue();
            payType=ALIPAY.getValue();
        } else{
//            payType=WX.getValue();
            payType=ALIPAY.getValue();
        }
        return this.getProductOrderServiceByPayType(payType).doPaymentNotify(notifyDate,request);
    }

    /**
     * 按时间获得未支付订单
     * @param minutes 分钟
     * @param remove  是否要删除
     * @param payType 付款类型
     * @return
     */
    @Override
    public List<ProductOrder> getNoPayOrderByDuration(int minutes, Boolean remove, String payType) {
        Instant minus = Instant.now().minus(Duration.ofMinutes(minutes));
        LambdaQueryWrapper<ProductOrder> queryWrapper=new LambdaQueryWrapper<>();
        //根据订单状态和支付类型查找
        queryWrapper.eq(ProductOrder::getStatus, PaymentStatusEnum.NOTPAY.getValue())
                .eq(StringUtils.isNotBlank(payType),ProductOrder::getPayType,payType);
        //如果是删除还要找状态是关闭的
        if (remove){
            queryWrapper.or().eq(ProductOrder::getStatus,PaymentStatusEnum.CLOSED.getValue());
        }
        //超过minutes时间的
        queryWrapper.and(p->p.le(ProductOrder::getCreateTime,minus));
        List<ProductOrder> list = productOrderService.list(queryWrapper);

        return list;
    }
}
